#!/bin/bash

# ======================================
# 网络连通性监测脚本（支持动态IP参数）
# 使用方式：./script.sh [目标IP]
# 示例：   ./script.sh 192.168.1.1
# 无参数时使用默认值：10.67.5.241
# 无参数时：检测 10.67.5.241:9092（IP+端口均支持动态配置）
# ======================================

# 1. 处理命令行参数
validate_ip() {
  local ip=$1
  # IPV4正则验证
  if [[ ! $ip =~ ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ ]]; then
    echo "error ip - $ip" >&2
    exit 1
  fi
}

validate_port() {
  local port=$1
  if [[ ! $port =~ ^[1-9][0-9]{0,3}$ ]] || (( port > 65535 )); then
    echo "error port - $port(port num : 1-65535)" >&2
    exit 1
  fi
}

# 1. 初始化默认值（IP+端口）
TARGET_IP="10.67.5.241"
TARGET_PORT=9092

# 解析参数（支持IP和端口）
if [ $# -ge 1 ]; then validate_ip "$1"; TARGET_IP="$1"; fi
if [ $# -ge 2 ]; then validate_port "$2"; TARGET_PORT="$2"; fi

# 2. 配置区（用户可自定义）
CHECK_INTERVAL=1             # 检测间隔（秒）
# LOG_FILE="$HOME/network_status.log"  # 日志存储路径
LOG_FILE="/var/log/network_status.log"  # 日志存储路径
MAX_PING_ATTEMPTS=2          # 每次检测发送的ping包数量
NC_TIMEOUT=2  # nc连接超时时间（秒）

# 3. 依赖检查（确保nc可用）
if ! command -v nc &> /dev/null; then
  echo "错误：未找到nc命令，请安装netcat（yum install nc 或 apt install netcat）" >&2
  exit 1
fi

# 4. 状态变量（新增端口状态）
last_ip_status="connected"
last_port_status="open"
failure_start_time=""

# 5. 日志文件初始化（保留sudo，因日志路径为/var/log）
sudo touch $LOG_FILE
sudo chmod 644 $LOG_FILE

# 6. 核心检测循环（整合IP和端口检测）
while true; do
  # === IP连通性检测 ===
  ping_result=$(ping -c "$MAX_PING_ATTEMPTS" -W 2 "$TARGET_IP" 2>&1)
  ip_return_code=$?
  ip_packet_loss=$(echo "$ping_result" | awk -F'%' '/packet loss/{print $1}' | awk '{print $NF}')
  
  # === 端口可用性检测（仅当IP可达时执行） ===
  if [ "$ip_return_code" -eq 0 ]; then
    port_result=$(nc -zv -w "$NC_TIMEOUT" "$TARGET_IP" "$TARGET_PORT" 2>&1)
    port_return_code=$?
    port_status=$(if [ "$port_return_code" -eq 0 ]; then echo "open"; else echo "closed"; fi)
  else
    port_status="ip-unreachable"  # IP不可达时，端口状态标记为不可达
  fi

  # === 状态判断（IP和端口独立处理） ===
  # IP状态
  ip_current_status=$(if [ "$ip_return_code" -eq 0 ] && [ "$ip_packet_loss" -lt 100 ]; then echo "connected"; else echo "disconnected"; fi)
  # 端口状态（IP可达时才判断端口是否开放）
  port_current_status=$(if [ "$ip_return_code" -eq 0 ]; then echo "$port_status"; else echo "ip-unreachable"; fi)

  # === 状态变化日志（IP和端口独立记录） ===
  timestamp=$(date "+%Y-%m-%d %H:%M:%S")
  
  # IP状态变化
  if [ "$ip_current_status" != "$last_ip_status" ]; then
    case $ip_current_status in
      "connected")
        if [ -n "$failure_start_time" ]; then
          duration=$(( $(date +%s) - $(date -d "$failure_start_time" +%s) ))
          log_entry="[IP-RECOVERY] 网络恢复 - 中断时长: ${duration}s"
          echo "$timestamp - $log_entry | IP: $TARGET_IP" | sudo tee -a "$LOG_FILE"
        fi
        ;;
      "disconnected")
        failure_start_time=$(date "+%s")  # 记录IP中断时间戳（秒级）
        log_entry="[IP-FAILURE] 网络中断 - IP: $TARGET_IP | 丢包率: ${ip_packet_loss}%"
        echo "$timestamp - $log_entry" | sudo tee -a "$LOG_FILE"
        port_current_status="ip-unreachable"  # IP中断时强制端口状态为不可达
        ;;
    esac
    last_ip_status=$ip_current_status
  fi

  # 端口状态变化（仅当IP可达时检测端口）
  if [ "$ip_return_code" -eq 0 ] && [ "$port_current_status" != "$last_port_status" ]; then
    case $port_current_status in
      "open")
        log_entry="[PORT-RECOVERY] 端口恢复 - $TARGET_IP:$TARGET_PORT"
        echo "$timestamp - $log_entry" | sudo tee -a "$LOG_FILE"
        ;;
      "closed")
        log_entry="[PORT-FAILURE] 端口关闭 - $TARGET_IP:$TARGET_PORT | 原因: $port_result"
        echo "$timestamp - $log_entry" | sudo tee -a "$LOG_FILE"
        ;;
    esac
    last_port_status=$port_current_status
  fi

  sleep "$CHECK_INTERVAL"
done
